package cn.csc.module.shoppingCard.service.card;

import cn.csc.framework.common.pojo.PageResult;
import cn.csc.framework.common.util.collection.CollectionUtils;
import cn.csc.framework.common.util.json.JsonUtils;
import cn.csc.framework.security.core.util.SecurityFrameworkUtils;
import cn.csc.module.member.api.user.MemberUserApi;
import cn.csc.module.member.api.user.dto.MemberUserRespDTO;
import cn.csc.module.shoppingCard.api.card.dto.CardMultiLockReqDTO;
import cn.csc.module.shoppingCard.controller.admin.card.vo.CardCreateReqVO;
import cn.csc.module.shoppingCard.controller.admin.card.vo.CardExportReqVO;
import cn.csc.module.shoppingCard.controller.admin.card.vo.CardPageReqVO;
import cn.csc.module.shoppingCard.controller.admin.card.vo.CardUpdateReqVO;
import cn.csc.module.shoppingCard.controller.app.card.vo.AppCardActivateReqVO;
import cn.csc.module.shoppingCard.convert.card.CardConvert;
import cn.csc.module.shoppingCard.dal.dataobject.card.CardDO;
import cn.csc.module.shoppingCard.dal.dataobject.project.CardProjectDO;
import cn.csc.module.shoppingCard.dal.mysql.card.CardMapper;
import cn.csc.module.shoppingCard.dal.mysql.project.CardProjectMapper;
import cn.csc.module.shoppingCard.dal.mysql.transaction.CardTransactionMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;

import java.math.BigInteger;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static cn.csc.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.csc.module.shoppingCard.enums.ErrorCodeConstants.*;

/**
 * 购物卡主表 Service 实现类
 *
 * @author liuchuang
 */
@Service
@Validated
@Slf4j
public class CardServiceImpl extends ServiceImpl<CardMapper, CardDO> implements CardService {

    @Autowired
    private MemberUserApi memberUserApi;

    @Autowired
    private CardProjectMapper cardProjectMapper;

    @Autowired
    private CardTransactionMapper cardTransactionMapper;


    @Override
    public BigInteger createCard(CardCreateReqVO createReqVO) {
        // 插入
        CardDO card = CardConvert.INSTANCE.convert(createReqVO);
        baseMapper.insert(card);
        // 返回
        return card.getId();
    }

    @Override
    public void updateCard(CardUpdateReqVO updateReqVO) {
        // 校验存在
        validateCardExists(updateReqVO.getId());
        // 更新
        CardDO updateObj = CardConvert.INSTANCE.convert(updateReqVO);
        baseMapper.updateById(updateObj);
    }

    @Transactional
    @Override
    public BigInteger activate(AppCardActivateReqVO reqVO) {
        log.info("activate 参数: {}", reqVO);
        CardDO cardDO = baseMapper.selectByCardNumber(reqVO.getCardNumber());
        if (cardDO == null || !reqVO.getPassword().equals(cardDO.getPassword())) {
            throw exception(CARD_PASSWORD_NOT_MATCH);
        }
        if (cardDO.getUserId() != null){
            throw exception(CARD_HAS_BIND);
        }
        cardDO.setUserId(BigInteger.valueOf(SecurityFrameworkUtils.getLoginUserId()));
        cardDO.setUserPhone(reqVO.getUserPhone());
        cardDO.setUpdater(String.valueOf(SecurityFrameworkUtils.getLoginUserId()));
        log.info("activate 更新实体: {}", cardDO);
        baseMapper.activate(cardDO);
        CardProjectDO cardProjectDO = cardProjectMapper.selectById(cardDO.getProjectId());
        cardProjectMapper.updateActivateNumById(cardProjectDO.getId(), cardProjectDO.getActivateNum()+1);
        return cardDO.getId();
    }

    @Override
    public int lockCard(BigInteger userId, BigInteger cardId, BigInteger orderId) {
        return baseMapper.lockCard(userId, cardId, orderId);
    }

    @Override
    public Boolean multiLockCard(List<CardMultiLockReqDTO> list){
        log.info("multiLockCard 参数: {}", JsonUtils.toJsonString(list));
        List<CardDO> cardDOS = CardConvert.INSTANCE.dtoToDos(list);
        log.info("multiLockCard 登录用户: {}", SecurityFrameworkUtils.getLoginUserId());
        cardDOS.forEach(c -> c.setUpdater(String.valueOf(SecurityFrameworkUtils.getLoginUserId())));
        return baseMapper.updateBatch(cardDOS,1000);
    }


    @Override
    public int unLockCard(BigInteger userId, BigInteger cardId, BigInteger orderId) {
        return baseMapper.unLockCard(userId, cardId, orderId);
    }

    @Override
    public int unLockCard(List<BigInteger> orderIds, BigInteger userId) {
        log.info("unLockCard 参数: {} , {}", userId, JsonUtils.toJsonString(orderIds));
        return baseMapper.unLockCard(userId, orderIds);
    }

    @Override
    public void deleteCard(BigInteger id) {
        // 校验存在
        validateCardExists(id);
        // 删除
        baseMapper.deleteById(id);
    }

    private void validateCardExists(BigInteger id) {
        if (baseMapper.selectById(id) == null) {
            throw exception(CARD_NOT_EXISTS);
        }
    }

    @Override
    public CardDO getCard(BigInteger id) {
        return baseMapper.selectById(id);
    }

    @Override
    public List<CardDO> getCardList(Collection<BigInteger> ids) {
        return baseMapper.selectBatchIds(ids);
    }

    @Override
    public List<CardDO> selectListByUserId(BigInteger userId) {
        return baseMapper.selectListByUserId(userId);
    }

    @Override
    public PageResult<CardDO> getCardPage(CardPageReqVO pageReqVO) {
        PageResult<CardDO> pageResult = baseMapper.selectPage(pageReqVO);
        if (CollectionUtils.isAnyEmpty(pageResult.getList())){
            return pageResult;
        }
        List<Long> updaters = pageResult.getList().stream().map(CardDO::getUpdater).filter(StringUtils::hasLength).distinct().
                map(Long::valueOf).collect(Collectors.toList());
        List<MemberUserRespDTO> users = memberUserApi.getUserList(updaters).getCheckedData();
        Map<Long, String> userMap = CollectionUtils.convertMap(users, MemberUserRespDTO::getId, MemberUserRespDTO::getName);
        pageResult.getList().stream().filter(c -> StringUtils.hasLength(c.getUpdater())).forEach(c -> c.setUpdater(userMap.get(Long.valueOf(c.getUpdater()))) );
        return pageResult;
    }

    @Override
    public List<CardDO> getCardList(CardExportReqVO exportReqVO) {
        return baseMapper.selectList(exportReqVO);
    }

}
